package com.ubao.network.resp;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.Hashtable;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;

import com.ubao.network.HttpConnection;
import com.ubao.network.HttpConstants;
import com.ubao.network.RequestInterface;
import com.ubao.network.ResponseInterface;

public class NewInfoResponse implements ResponseInterface {

	private Hashtable hash = new Hashtable();

	private int totalRecord = 0;

	public final static String NEW_INFO_EXCEPTION = "New Info Return Error!";

	public NewInfoResponse() {
	}

	/**
	 * 读取返回信息
	 * 
	 * @return
	 * @throws Exception
	 */
	private byte[] readResponse(HttpURLConnection conn, InputStream inputStream)
			throws Exception {
		try {
			byte[] data = null;
			if (conn != null && inputStream != null) {
				int len = (int) conn.getContentLength();
				// 读取模式1：直接获取数据长度

				if (conn.getRequestMethod().equals(HttpConnection.HEAD)) {

					return null;
				}

				if (len <= 0) {
					// 读取模式2：从Http连接头获取数据长度
					String bodyLength = null;
					bodyLength = conn.getHeaderField("content-length");

					if (bodyLength != null) {
						try {
							len = Integer.parseInt(conn
									.getHeaderField("Body-Length"));
						} catch (Exception e) {
							// e.printStackTrace();
							throw e;
						}
					}
				}

				if (len > 0) {
					int actual = 0;
					int bytesread = 0;
					data = new byte[len];
					while ((bytesread != len) && (actual != -1)) {
						actual = inputStream.read(data, bytesread, len
								- bytesread);
						// logger.debug("actual: " + actual);
						if (actual >= 0) {
							bytesread += actual;
						}
					}

					if (bytesread == 0) {
						return null;
					} else if (bytesread < len) {
						byte[] actualData = new byte[bytesread];
						System.arraycopy(data, 0, actualData, 0, bytesread);

						return actualData;
					}
				} else {
					// 读取模式3：持续读取，直到数据包结束
					ByteArrayOutputStream tmp = new ByteArrayOutputStream();
					byte[] buffer = new byte[HttpConstants.BUFFER_SIZE];
					int count;
					while ((count = inputStream.read(buffer, 0,
							HttpConstants.BUFFER_SIZE)) != -1) {
						tmp.write(buffer, 0, count);
					}
					data = tmp.toByteArray();
					tmp.close();
					tmp = null;
					buffer = null;
				}
			}
			return data;
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		}
		// return null;
	}

	public void setData(HttpURLConnection conn, InputStream inputStream,
			RequestInterface request, boolean isCmwap) throws Exception {
		final byte[] bytes = readResponse(conn, inputStream);
		analysisData(bytes);
	}

	public void analysisData(byte[] responseData) throws Exception {
		StructResponse struct = new StructResponse(responseData);
		System.out.println("responseSize:" + responseData.length);
		byte[] data = null;
		// try {
		int nPkgSize = struct.readInt(); // 包的大小
		int nMsId = struct.readShort(); // 消息编码
		int nOwnerId = struct.readInt(); // 处理返回消息的窗口指针
		int bResult = struct.readByte(); // 请求是否成功(若失败，后继的为错误消息包)，0表示失败，1表示成
		if (bResult == 0) {
			throw new Exception(NEW_INFO_EXCEPTION);
		}
		int bEncrypt = struct.readByte(); // 是否为加密消息
		int bCompressed = struct.readByte(); // 是否为压缩数据包
		int nMagicId = struct.readInt();

		if (bCompressed == 1) {// 如果是压缩数据包
			int nOriginalSize = struct.readInt();// 未压缩的字节数
			int nCompressedSize = struct.readInt();// 压缩后的字节数
			byte[] strData = struct.readByteArray(nCompressedSize);// 压缩数据
			byte[] resultData = decompress(strData, nCompressedSize,
					nOriginalSize);
			StructResponse response = new StructResponse(resultData);
			convertExceptHeader(response);
		} else {// 如果是非压缩数据包，继续往下读
			convertExceptHeader(struct);
		}
	}

	private byte[] convertExceptHeader(StructResponse struct) {
		byte[] data = null;
		int nType = struct.readInt();
		int nLen = struct.readInt();
		int nFlag = struct.readShort();
		int nMsgId = struct.readShort();
		int nMsgLen = struct.readInt();
		int nCategory = struct.readByte();
		int nExtra1 = struct.readByte();
		int nExtra2 = struct.readShort();
		int nExtra3 = struct.readInt();
		totalRecord = nExtra3;
		data = struct.readByteArray(nMsgLen);
		putData(nCategory, data);
		return data;
	}

	public int getTotalRecord() {
		return totalRecord;
	}

	private byte[] decompress(byte[] data, int beforeDecompressSize,
			int afterDecompressSize) {

		Inflater decompresser = new Inflater();
		decompresser.setInput(data, 0, beforeDecompressSize);
		// 对byte[]进行解压，同时可以要解压的数据包中的某一段数据，就好像从zip中解压出某一个文件一样。
		byte[] result = new byte[afterDecompressSize];

		try {
			decompresser.inflate(result);
		} catch (DataFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			result = null;
		}
		decompresser.end();

		return result;
	}

	private void putData(int type, byte[] data) {
		String key = Integer.toString(type);
		if (hash.containsKey(key))// 处理key冲突
		{
			byte[] tempData = (byte[]) hash.get(key);
			data = mergeTwoByteArray(tempData, data);
		}
		if (null != data && data.length != 0) {
			hash.put(key, data);
		}
	}

	private byte[] mergeTwoByteArray(byte[] arr1, byte[] arr2) {// 合并两个byte数组
		int arr1Length = (arr1 == null) ? 0 : arr1.length;
		int arr2Length = (arr2 == null) ? 0 : arr2.length;
		int totalLength = arr1Length + arr2Length;

		if (totalLength < 1)
			return null;

		byte[] temp = new byte[totalLength];
		if (arr1Length > 0)
			System.arraycopy(arr1, 0, temp, 0, arr1Length);
		if (arr2Length > 0)
			System.arraycopy(arr2, 0, temp, arr1Length, arr2Length);

		return temp;
	}

	public byte[] getData(int key) {
		return (byte[]) hash.get(key + "");
	}
}
